/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package cn.ac.iie.di.worker;

import cn.ac.iie.di.datadock.rdata.exchange.client.core.REFieldType;
import cn.ac.iie.di.global.GlobalParas;
import cn.ac.iie.di.redisutil.RedisUtil;
import cn.ac.iie.di.util.GenerateMD5;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;

/**
 *
 * @author shipengfeng
 */
public class DownPicAction implements Runnable {

    public static Logger log = Logger.getLogger(DownPicAction.class.getName());

    RedisUtil redisUtil;
    private static Object dirLock = new Object();

    private static boolean makeDir(File dir) {
        synchronized (dirLock) {
            if (dir.exists()) {
                return true;
            } else {
                return dir.mkdirs();
            }
        }
    }

    @Override
    public void run() {

        while (true) {
            try {
                ArrayList list = (ArrayList) GlobalParas.urlAndAddrPool.poll(20, TimeUnit.MILLISECONDS);
                if (list == null) {
                    if (GlobalParas.killDPAction) {
                        break;
                    }
                    continue;
                }
                HashMap map = (HashMap) list.get(0);
                String urlandAddrs = (String) list.get(1);
//                                log.info(urlandAddrs);
                String urlandAddr = "";

                //存储真实url和地址
                String[] strings = new String[urlandAddrs.split("[$]").length];

                for (int i = 0; i < strings.length; i++) {
                    urlandAddr = urlandAddrs.split("[$]")[i];
//                                        log.info(urlandAddr);
                    if (urlandAddr.split("[￥]").length != 3) {
                        log.error("wrong urlandAddr ");
                        continue;
                    }
                    String trueUrl = urlandAddr.split("[￥]")[0];
                    String filePath = urlandAddr.split("[￥]")[1];
                    String dwdUrl = urlandAddr.split("[￥]")[2];

                    redisUtil = GlobalParas.redisUtil;
                    String url2MD5 = GenerateMD5.string2MD5(dwdUrl);

                    if (!redisUtil.exists(url2MD5)) {
                        //通过时间来判断是否新建文件夹
                        File f = new File(GlobalParas.rootPath + File.separator + filePath);
                        while (!makeDir(f.getParentFile())) {
                            log.warn("can not create dir " + f.getParentFile().getPath());
                            try {
                                Thread.sleep(30000);
                            } catch (Exception ex) {
                            }
                        }
                        // 提取url
                        URL url;
                        try {
                            if (GlobalParas.isTwb == 1) {
                                url = new URL(GlobalParas.httpUrl + trueUrl);
                            } else {
                                url = new URL(trueUrl);
                            }
                        } catch (Exception ex) {
                            log.error(ex.getMessage(), ex);
                            continue;
                        }

                        int numTry = 0;
                        long sleepTime = 1000;
                        long startTime = System.currentTimeMillis();
                        while (true) {
                            //下载成功以后，将url的md5值和它存储的地址存放在redis中
                            try {
                                FileUtils.copyURLToFile(url, f, GlobalParas.maxConnTimeLimit, GlobalParas.maxReadTimeLimit);
                                log.info("DownPic success use " + (System.currentTimeMillis() - startTime) + " ms" + " size: " + f.length());
                                String res = null;
                                //redis 插入超时，需要报错么？
                                res = redisUtil.setex(url2MD5, filePath, GlobalParas.redisTimeout);
                                strings[i] = "0|" + filePath + "|" + GlobalParas.localhostName + "|" + trueUrl;
                                break;
                            } catch (Exception ex) {
                                if (GlobalParas.killDPAction) {
                                    strings[i] = "";
                                    log.error("DownPic failed  " + trueUrl + "  MD5 is " + url2MD5 + " addr is " + filePath, ex);
                                    break;
                                }
                                Thread.sleep(sleepTime);
                                log.warn("sleep time is : " + sleepTime);
//                                sleepTime = sleepTime * GlobalParas.maxTry;
                                if (numTry >= GlobalParas.maxTry) {
                                    strings[i] = "";
                                    log.error("DownPic failed  " + trueUrl + "  MD5 is " + url2MD5 + " addr is " + filePath, ex);
                                    break;
                                }
                                numTry++;
                            }
                        }
                        //如果在redis中找到图片已经下载，则直接拷贝已经下载的图片，并存放在指定的目录
                    } else {
                        log.info("Message in redis ");
                        String oldFileString = redisUtil.get(url2MD5);
                        strings[i] = "1|" + oldFileString + "|" + GlobalParas.localhostName + "|" + trueUrl;
                    }

                }

                //遍历图片存储路径的字符串数组
                List list1 = new LinkedList();

                //将存放图片地址的字符串字段添加在消息中
                if (strings != null && strings.length != 0) {
                    for (int i = 0; i < strings.length; ++i) {
                        if (!strings[i].equals("")) {
                            //只要字符串数组中有一个非空串，则将该条消息回传，否则不回传
                            list1.add(REFieldType.Strings);
                            list1.add(strings);
                            //添加ifexists字段，字段的内容是一个String数组，数组中的每个值都是对应的url真实的存在的地方
                            map.put(GlobalParas.newColumn, list1);
                            //回传这个添加了额外字段的消息
                            if (!GlobalParas.sendMsgPool.offer(map)) {
//                                                                log.warn("GlobalParas.sendMsgPool is full!");
                                while (true) {
                                    Thread.sleep(500);
                                    if (GlobalParas.sendMsgPool.offer(map)) {
//                                                                                log.info(" give message to sendMsgPool ");
                                        break;
                                    }
                                }
                            }
                            HashMap mapForHttp = new HashMap();
                            Iterator ite = map.entrySet().iterator();
                            while (ite.hasNext()) {
                                Map.Entry entry = (Map.Entry) ite.next();
                                String k = (String) entry.getKey();
                                List v = (List) entry.getValue();
                                mapForHttp.put(k, v);
                            }
                            if (!GlobalParas.myRequestPool.offer(mapForHttp)) {
                                while (true) {
                                    Thread.sleep(500);
                                    if (GlobalParas.myRequestPool.offer(mapForHttp)) {
                                        break;
                                    }
                                }
                            }
                            break;
                        }
                    }
                }

                if (GlobalParas.killDPAction) {
                    break;
                }

            } catch (Exception e) {
                log.error(e, e);
            }
        }

        if (!GlobalParas.DwdPicAQueue.isEmpty()) {
            GlobalParas.DwdPicAQueue.poll();
            log.info("GlobalParas.DwdPicAQueue size is : " + GlobalParas.DwdPicAQueue.size());
        }
        log.info("DownPic Action exit ");
    }

}
